#ifdef _WIN32
#include <windows.h>
#else
#include <GL/glx.h>
#endif

#include <iostream>

#include "floor.h"
#include "robot.h"

#define BUFFER_OFFSET(i) ((char *)NULL + (i))

Floor::Floor()
{
}

void Floor::initializeVertexBuffer()
{
    const float radius = 50.0f;
	const float height= 0.0f;
    //Push back 8 vertices that make up a cube
    m_vertices.push_back(Vertex(-radius, -height,  radius));
    m_vertices.push_back(Vertex(-radius, -height, -radius));
    m_vertices.push_back(Vertex(radius, -height, -radius));
    m_vertices.push_back(Vertex(radius, -height,  radius));

    //Push back the indices that make up the triangles for each face.
    m_indices.push_back(0);
    m_indices.push_back(2);
    m_indices.push_back(3);
    m_indices.push_back(0);
    m_indices.push_back(1);
    m_indices.push_back(2);

    glBindBuffer(GL_ARRAY_BUFFER, m_vbos[VERTEX_BUFFER]); //Bind the vertex buffer
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * m_vertices.size(), &m_vertices[0], GL_STATIC_DRAW); //Send the data to OpenGL

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbos[INDEX_BUFFER]); //Bind the vertex buffer
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * m_indices.size(), &m_indices[0], GL_STATIC_DRAW); //Send the data to OpenGL
}

void Floor::initializeVertexColors()
{
    /*
        We build an array of colors, 8 reds, 8 blues, 8 yellows and 8 whites.
        This is because there are 8 vertices in a cube, we switch the color by
        setting the BUFFER_OFFSET to glColorPointer to point at each block
        of colors before rendering with glDrawElements
    */

    float green [] = { 0.0f, 1.0f, 0.0f };
    for (int i = 0; i < 4; ++i) {
        m_colorBuffer.push_back(Color(green[0], green[1], green[2]));
    }
    //Send the color data to OpenGL
    glBindBuffer(GL_ARRAY_BUFFER, m_vbos[COLOR_BUFFER]); //Bind the vertex buffer
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * m_colorBuffer.size(), &m_colorBuffer[0], GL_STATIC_DRAW); //Send the data to OpenGL
}

void Floor::render()
{
	initialize();
	//glScalef(30.0f, 30.0f, 30.0f);
    //glLoadIdentity();					// reset matrix
	glTranslatef(0.0f, -10.0f, -30.0f);;
    glDrawElements(GL_TRIANGLES, m_indices.size(), GL_UNSIGNED_INT, 0);

}

bool Floor::initialize()
{
#ifdef _WIN32
    glGenBuffers = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffers");
    glBindBuffer = (PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer");
    glBufferData = (PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData");
#else
    glGenBuffers = (PFNGLGENBUFFERSARBPROC)glXGetProcAddress((const GLubyte*)"glGenBuffers");
    glBindBuffer = (PFNGLBINDBUFFERPROC)glXGetProcAddress((const GLubyte*)"glBindBuffer");
    glBufferData = (PFNGLBUFFERDATAPROC)glXGetProcAddress((const GLubyte*)"glBufferData");
#endif

    if (!glGenBuffers || !glBindBuffer || !glBufferData)
    {
        std::cerr << "VBOs are not supported by your graphics card" << std::endl;
        return false;
    }

    glGenBuffers(LAST_BUFFER, m_vbos); //Generate a buffer for the vertices, indices and colors

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);

    initializeVertexBuffer(); //Build up the array of vertices for the cube
    initializeVertexColors(); //Build up an array of colors for the robot

    //Set the vertex pointer for the cube
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbos[INDEX_BUFFER]); //Bind the vertex buffer
    glBindBuffer(GL_ARRAY_BUFFER, m_vbos[VERTEX_BUFFER]);
    glVertexPointer(3, GL_FLOAT, 0, 0);

    //Bind the default color as white, this changes depending on the part of the robot we are drawing
    glBindBuffer(GL_ARRAY_BUFFER, m_vbos[COLOR_BUFFER]);
    glColorPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(WHITE_OFFSET)); //Default color white


    return true;
}